#include "circuit.h"
#include "simulate.h"
#include "alg.h"
#include <string.h>

int HG_CNT;
extern Circuit *C;
queue<Node*> worklist;

bool formHybrid();

bool moveContainer(HybridNode* hn)
{
        list<int>::iterator it;
        for(it = hn->inputs_.begin(); it != hn->inputs_.end(); it++)
                hn->inputs.push_back(C->getSignal(*it));
        for(it = hn->outputs_.begin(); it != hn->outputs_.end(); it++)
                hn->outputs.push_back(C->getSignal(*it));
}

bool showFormResult()
{
        int i;
        
        for(i = 0; i < C->gateSize(); i++)
        {
                cout<< i <<endl;
                cout << "Gate Index " << C->getGate(i)->getGateIndex() << endl;
                cout << "Gate Name " << C->getGate(i)->getName() <<endl;
                cout << "Gate Belonging " << " HG " << C->getGate(i)->HG_ID << endl;
                cout<<C->getGate(i)->getOutput(0)->getName()<<endl;
        }
        
        return true;
}

bool dumpInputs(list<int> inputs)
{
        list<int>::iterator it;
        //cout<<"inputs in HG are"<<endl;
        
        for(it = inputs.begin(); it != inputs.end(); it++)
                cout << C->getSignal(*it)->getName() <<"\t";
        cout<<endl;
        
        return true;
}

//check for opportunity to merge, the result might not be the best, the
//trade off is the best. 2 means don't care
bool checkMerge(HybridNode* hn, int* event, const int size, int mode)
{
        int cnt, pos, k;
        vector<int*>::iterator it;
        cout<<"size is "<<hn->OFR0.size()<<endl;
        if(mode == 0)
        {
                for(it = hn->OFR0.begin(); it != hn->OFR0.end(); it++)
                {
                        cnt = 0;
                        for(k = 0; k < size; k++)
                                if((*it)[k] != event[k])
                                {
                                        pos = k;
                                        cnt++;
                                }
                        
                        
                        if(cnt == 1)
                                (*it)[pos] = 2; 
                        else
                        {
                                
                                return true;
                                hn->OFR0.push_back(event);
                                
                        }
                }
        }
        else
        {
                for(it = hn->OFR1.begin(); it != hn->OFR1.end(); it++)
                {
                        cnt = 0;
                        for(k = 0; k < size; k++)
                                if((*it)[k] != event[k])
                                {
                                        pos = k;
                                        cnt++;
                                }
                        
                        
                        if(cnt == 1)
                                (*it)[pos] = 2; 
                        else
                        {
                                
                                return true;
                                hn->OFR1.push_back(event);
                                
                        }
                }
        }
        
        return false;
}

bool calEvents(HybridNode* hn)
{
        int** tab;
        int i,j,bit;
        int cnt0 = 0,cnt1 = 0;
        
        tab = new int*[hn->getInputsSize() + hn->getOutputsSize()];
        int entry = pow(2,hn->getInputsSize() + hn->getOutputsSize()-1);
        for(i = 0; i < hn->getInputsSize() + hn->getOutputsSize(); i++)
                tab[i] = new int[entry];

        for(i = 0; i < hn->getInputsSize() + hn->getOutputsSize(); i++)
                for(j = 0;j < entry; j++)
                        tab[i][j] = -1;
        
        list<Signal*> sigList;
	//int* val;
        //val = new int[C->signalSize()];
        //memset(val,2,sizeof(int)*C->signalSize());
        
        bool cont=false;
        for(j = 0; j < C->signalSize(); j++)
                C->getSignal(j)->setVal(Z);
        
        for(j = 0; j < hn->getInputsSize(); ++j)
                C->getSignal(hn->getInput(j))->setVal(Z);
        
        for(j = 0; j < hn->getOutputsSize(); ++j)
                C->getSignal(hn->getOutput(j))->setVal(Z);
        
        /*
        ofstream out("Check",ios_base::app);
        cout<<"Output signal is "<< C->getSignal(hn->getOutput(0))->getName() << endl;
        cout<<"Inputs are"<<endl;
        for(i = 0; i < hn->getInputsSize(); i++)
                cout<< C->getSignal(hn->getInput(i))->getName()<<"\t";
        cout<<endl;
        
        cout<<"HGate ID" << hn->index << endl;
        */

        //first round, obtain the truth table
        for(i = 0; i < entry; i++)
        {
                
                sigList.clear();
                
                for(j = 0; j < hn->getInputsSize(); ++j)
                        C->getSignal(hn->getInput(j))->setVal(Z);
                
                for(j = 0; j < hn->getOutputsSize(); ++j)
                        C->getSignal(hn->getOutput(j))->setVal(Z);
                
                bit = i;
                for(j = 0; j < hn->getInputsSize(); ++j){
                        if(bit >= 2)
                        {
                                if(bit % 2 == 0)
                                        C->getSignal(hn->getInput(j))->setVal(Zero);
                                else
                                        C->getSignal(hn->getInput(j))->setVal(One);
                                //val[hn->getInput(j)] = C->getSignal(hn->getInput(j))->getVal();
                                sigList.push_back(C->getSignal(hn->getInput(j)));
                        }
                        else
                        {
                                if(bit == 0)
                                        C->getSignal(hn->getInput(j))->setVal(Zero);
                                else
                                        C->getSignal(hn->getInput(j))->setVal(One);
                                
                                //val[hn->getInput(j)] = C->getSignal(hn->getInput(j))->getVal();
                                sigList.push_back(C->getSignal(hn->getInput(j)));
                        }
                        bit /= 2;
                }
                
                for(j = 0; j < hn->getInternalSize(); ++j)
                        sigList.push_back(C->getSignal(hn->getInternal(j)));
                
                //out<<"_____________________________________"<<i<<endl;
                //out<<"Current Entry is "<<i<<endl;
                //out<<"_____________________________________"<<i<<endl;
                
                Signal *s;
                while (!sigList.empty())
                {
                        s = sigList.front();
                        sigList.erase(sigList.begin());
                        
                        if(s->getVal() == 2)
                        {
                                sigList.push_back(s);
                                continue;
                                
                        }
                                 
#ifdef DEBUG_SIMULATE
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();
#endif   
                        
                        if(s->outputSize()!=0){
                                if(s->getOutput(0)->signature()!=INPUT){
                                        for(int i=0; i<s->outputSize(); ++i){
                                                if(s->getOutput(i)->isActive()){
                                                }
                                        }
                                }
                                else{
                                        
                                        for(int i=1; i<s->outputSize(); ++i){
                                                if(s->getOutput(i)->isActive()){
                                                }
                                        }
                                }
                        }
                        if(s->getIndex() == hn->getOutput(0))
                                break;
                }
        
                if(C->getSignal(hn->getOutput(0))->getVal() == 2)
                {
                        cout<<"No Way!"<<endl;
                        cin.get();
                }
                else
                {
                        tab[hn->getInputsSize() + hn->getOutputsSize()-1][i] 
                                = C->getSignal(hn->getOutput(0))->getVal();
                        
                        if(C->getSignal(hn->getOutput(0))->getVal() == 0)
                                cnt0++;
                        else
                                cnt1++;
                }
        }
        
        //cout<<"count 0 is "<<cnt0<<endl;
        //cout<<"count 1 is "<<cnt1<<endl;
        int tab_row,tab_col;
        int* temp;
        temp = new int[hn->getInputsSize() + hn->getOutputsSize()];
        
        //retrive for other inputs value
        for(i = 0; i < entry; i++)
        {
                bit = i;
                memset(temp, -1, 
                       (hn->getInputsSize() + hn->getOutputsSize())* sizeof(int));
                
                for(j = 0 ; j < hn->getInputsSize(); j++){
                        //for(j = hn->getInputsSize(); j != 0; j--){
                        if(bit >= 2)
                                temp[j] = bit % 2;
                        else
                                temp[j] = bit;
                        bit /= 2;
                }
                
                //if(tab[hn->getInputsSize() + hn->getOutputsSize() - 1][i] >= 2 || tab[hn->getInputsSize() + hn->getOutputsSize() - 1][i]<0)
                //cout<<"No Way!!!"<<endl;
                
                temp[hn->getInputsSize()] =
                        tab[hn->getInputsSize() + hn->getOutputsSize() - 1][i];
                
                for(tab_row = 0 ; tab_row < hn->getInputsSize(); tab_row++){
                            
                        bit = 0;
                        tab_col = 0;
                        
                        for(j = 0 ; j < hn->getInputsSize() + hn->getOutputsSize(); j++){
                                if(j == tab_row)
                                        continue;
                                else
                                {
                                        tab_col += temp[j] * pow(2,bit++);
                                }
                        }
                        
                        //cout<<"LOKKOKOKOKOKOKO,......"<<endl;
                        //cout<<tab_col<<endl;
                        //if(tab_col >= pow(2,hn->getInputsSize() + hn->getOutputsSize()))
                        //cout<<"SHITSHITSHIT"<<endl;
                        
                        if(tab[tab_row][tab_col] == -1)
                                tab[tab_row][tab_col] = temp[tab_row];
                        else//-2 means the entry have been
                                //entered twice, thus not tracible
                                tab[tab_row][tab_col] = -2;
                }
        }
        
        /*
        cout<<"All entry retrieved!"<<endl;
        for(tab_row = 0 ; tab_row < hn->getInputsSize() + hn->getOutputsSize(); tab_row++){
                for(tab_col = 0 ; tab_col < pow(2,hn->getInputsSize()); tab_col++){
                        cout<<tab[tab_row][tab_col]<<"\t";
                }
                cout<<endl;
        }
        */

        int k;
        hn->events = new int*[2*hn->getInputsSize()];
        for(k = 0; k < 2*hn->getInputsSize(); k++)
                hn->events[k] = new int[hn->getInputsSize()];
        
        for(k = 0; k < 2*hn->getInputsSize(); k++)
                memset(hn->events[k], -1, sizeof(int) * hn->getInputsSize());
        
        //create event
        for(i = 0; i < hn->getInputsSize() + hn->getOutputsSize(); i++)
        {       
                for(j = 0; j < entry; j++)
                {
                        int* event = new int[hn->getInputsSize()];
                        memset(event, -1, sizeof(int) * hn->getInputsSize());
                        if(tab[i][j] == -1 || tab[i][j] == -2)
                                continue;
                        else
                        {
                                bit = j;
                                for(k = 0; k < hn->getInputsSize(); k++)
                                {
                                        if(bit >= 2)
                                                event[k] = bit % 2;
                                        else
                                                event[k] = bit;
                                        bit /= 2;
                                }
                        }
                        
                        //for(k = 0 ; k < hn->getInputsSize(); k++)
                        //cout<< event[k] << "\t";
                        //cout<<endl;
                        
                        int cnt, pos, flag=0;
                        vector<int*>::iterator it;
                        //if it is Output
                        if(i == hn->getInputsSize() + hn->getOutputsSize()-1)
                        {
                                if(tab[i][j] == 0)
                                {
                                        if(hn->OFR0.size() == 0)
                                        {
                                                hn->OFR0.push_back(event);
                                                continue;
                                        }
                                                
                                        for(it = hn->OFR0.begin(); it != hn->OFR0.end(); it++)
                                        {
                                                cnt = 0;
                                                for(k = 0; k < hn->getInputsSize(); k++)
                                                        if((*it)[k] != event[k])
                                                        {
                                                                pos = k;
                                                                cnt++;
                                                        }
                                                        
                                                if(cnt == 1)
                                                {
                                                        flag = 1;
                                                        (*it)[pos] = 2; 
                                                        break;
                                                }
                                        }
                                                
                                        if(flag == 0)
                                                hn->OFR0.push_back(event);
                                }
                                
                                if(tab[i][j] == 1)
                                {
                                        if(hn->OFR1.size() == 0)
                                        {
                                                hn->OFR1.push_back(event);
                                                continue;
                                        }
                                        
                                        for(it = hn->OFR1.begin(); it != hn->OFR1.end(); it++)
                                        {
                                                cnt = 0;
                                                for(k = 0; k < hn->getInputsSize(); k++)
                                                        if((*it)[k] != event[k])
                                                        {
                                                                pos = k;
                                                                cnt++;
                                                        }
                                                
                                                if(cnt == 1){
                                                        flag = 1;
                                                        (*it)[pos] = 2; 
                                                        break;
                                                }
                                        }
                                        
                                        if(flag == 0)
                                                hn->OFR1.push_back(event);
                                }
                        }
                        else//Inputs
                        {
                                if(tab[i][j] == 0)
                                {       
                                        if(hn->events[2*i+0][0] == -1)
                                                for(k = 0; k < hn->getInputsSize(); k++)
                                                        hn->events[2*i+0][k] = event[k];
                                        else
                                        {
                                                cnt=0;
                                                for(k = 0; k < hn->getInputsSize(); k++)
                                                        if(hn->events[2*i+0][k] != event[k])
                                                        {
                                                                pos = k;
                                                                cnt++;
                                                        }

                                                if(cnt == 1)//can merge
                                                        hn->events[2*i+0][pos] = 2;
                                                else
                                                {
                                                        int *temp = new int[hn->getInputsSize() + 2];
                                                        temp[0] = i; temp[1] = 0;
                                                        for(k = 0; k < hn->getInputsSize();k++)
                                                                temp[k+2] = event[k];
                                                        hn->extra_events.push_back(temp);
                                                }                                                
                                        }
                                }
                                
                                if(tab[i][j] == 1)
                                {
                                        if(hn->events[2*i+1][0] == -1)
                                                for(k = 0; k < hn->getInputsSize(); k++)
                                                        hn->events[2*i+1][k] = event[k];
                                        else
                                        {
                                                cnt=0;
                                                for(k = 0; k < hn->getInputsSize(); k++)
                                                        if(hn->events[2*i+1][k] != event[k])
                                                        {
                                                                pos = k;
                                                                cnt++;
                                                        }

                                                if(cnt == 1)//can merge
                                                        hn->events[2*i+1][pos] = 2;
                                                else
                                                {
                                                        int *temp = new int[hn->getInputsSize() + 2];
                                                        temp[0] = i; temp[1] = 1;
                                                        for(k = 0; k < hn->getInputsSize(); k++)
                                                                temp[k+2] = event[k];
                                                        hn->extra_events.push_back(temp);
                                                }
                                        }
                                }
                        }
                }
        }
        /*
        vector<int*>::iterator it;
        cout << "dumping output forward restore '0'! "<<endl;                                                                                                  
        for(it = hn->OFR0.begin(); it != hn->OFR0.end(); it++)
        {
                for(j = 0; j < hn->getInputsSize(); j++)
                        cout<<(*it)[j]<<"\t";
                cout<<endl;
        }
                                
        cout << "dumping output forward restore '1'! "<<endl;                                                                                                  
        for(it = hn->OFR1.begin(); it != hn->OFR1.end(); it++)
        {
                for(j = 0; j < hn->getInputsSize(); j++)
                        cout<<(*it)[j]<<"\t";
                cout<<endl;
        }
              
        for(j = 0; j < 2 * hn->getInputsSize(); j++)
        {
                cout<<"Back Track input "<< j/2 << " restore "<< j%2 <<endl;
                for(k = 0; k < hn->getInputsSize(); k++)
                        cout<<hn->events[j][k]<<"\t";
                cout<<endl;
        }
        */    
        for(i = 0; i < hn->getInputsSize() + hn->getOutputsSize(); i++)
                delete tab[i];
        delete tab;
        
        return true;
}

bool findPre(Node* n, HybridNode* hn, int &flag)
{ 
        int i,j;
        list<int>::iterator it;
        list<int>::iterator it2;
        list<int> tmp_inputs_union(50);
        list<int> pt_inputs_remove;
        list<int> tmp_inputs;//in the list are the index of input signals 
        vector<int>::iterator it_;
        vector<int> pt_gates_insert;
        vector<int> tmp_gates_union(50);

        //have to use BFS
        //n->inputSize() can only be 1 or 2, they are signals
        //flow:
        //node_root->signal->node_b1->node_b2

        //the first thing, test whether each input of the gate is "valid"
        //for grouping
        
        //the second thing is to put all the inputs of noe_b1 and node_b2
        //to the temp vector to see whether there are any overlapp                        
        //cout<<"NEW ROUND!"<<endl; 
      
        for(i = 0; i < n->inputSize(); i++)
        {
                if( n->getInput(i)->outputSize() == 2 ) 
                        if( find(hn->indexes.begin(), hn->indexes.end(), n->getInput(i)->getOutput(0)->getGateIndex()) == hn->indexes.end() ||
                            find(hn->indexes.begin(), hn->indexes.end(), n->getInput(i)->getOutput(1)->getGateIndex()) == hn->indexes.end() )
                                return false;

                if( (n->getInput(i)->outputSize() > 2 ) ||
                    (n->getInput(i)->outputSize() == 1 && n->getInput(i)->getInput(0)->HG_ID != -1) ||
                    (n->getInput(i)->outputSize() == 1 && n->getInput(i)->getInput(0)->signature() == 4) ||
                    (n->getInput(i)->outputSize() == 1 && n->getInput(i)->getInput(0)->signature() == 1) ||
                    (n->getInput(i)->outputSize() == 1 && n->getInput(i)->getInput(0)->signature() == 2) ||
                    (n->getInput(i)->outputSize() == 1 && n->getInput(i)->getInput(0)->getName().c_str()[0] == 'b') ||
                    (n->getInput(i)->outputSize() == 1 && n->getInput(i)->getInput(0)->getName().c_str()[0] == 'n') )
                        //this node is done
                        return false;
        }
        
                
        for(i = 0; i < n->inputSize(); i++)
        {
                
                pt_gates_insert.push_back(n->getInput(i)->getInput(0)->getGateIndex());
                if(n->getInput(i)->getName().c_str()[0] == 'b')
                {
                        cout<<n->getOutput(0)->getName()<<endl;
                        cin.get();
                }
                
                
                pt_inputs_remove.push_back(n->getInput(i)->getIndex());
                
                for(j = 0; j < n->getInput(i)->getInput(0)->inputSize(); j++)
                {
                        /*
                          if(n->getInput(i)->getInput(0)->inputSize() == 1 &&  n->getInput(i)->getInput(0)->signature() == 3)//inverter
                          {
                          it = hn->findInput(n->getInput(i)->getIndex());
                          if(it != hn->inputs.end())
                          {       
                          cout<<"signal name "<< n->getInput(i)->getName() << endl;
                          cout<<n->getInput(i)->getIndex()<<endl;
                          }
                                
                          hn->delInput(it);
                          hn->addInput(n->getInput(i)->getInput(0)->getInput(0)->getIndex());
                          n->getInput(i)->getInput(0)->HG_ID = hn->index;
                          worklist.push(n->getInput(i)->getInput(0));
                          }
                          else
                          {
                          tmp_inputs.push_back(n->getInput(i)->getInput(0)->getInput(j)->getIndex());
                          }
                        */
                        tmp_inputs.push_back(n->getInput(i)->getInput(0)->getInput(j)->getIndex());
                }
        }
               
        //check overlapp
        tmp_inputs.sort();
        hn->inputs_.sort();
        it = set_union(tmp_inputs.begin(),tmp_inputs.end(),hn->inputs_.begin(),hn->inputs_.end(),tmp_inputs_union.begin());
        tmp_inputs_union.resize(distance(tmp_inputs_union.begin(), it));
        tmp_inputs_union.sort();
        it = unique(tmp_inputs_union.begin(),tmp_inputs_union.end());
        tmp_inputs_union.resize(distance(tmp_inputs_union.begin(), it));
        
        //first round, allow increase
        if(flag == 0)
        {
                if(hn->inputs_.size() <= 4)
                {
                        hn->inputs_.clear();
                        for(it = tmp_inputs_union.begin(); it != tmp_inputs_union.end(); it++)
                                if(find(pt_inputs_remove.begin(),pt_inputs_remove.end(),*it) == pt_inputs_remove.end())
                                        hn->inputs_.push_back(*it);
                        
                        hn->internal.insert(hn->internal.begin(),pt_inputs_remove.begin(),pt_inputs_remove.end());
                                                
                        //use this as a temporary container
                        it_ = set_union(hn->indexes.begin(),hn->indexes.end(), pt_gates_insert.begin(), pt_gates_insert.end(), tmp_gates_union.begin());
                        tmp_gates_union.resize(distance(tmp_gates_union.begin(), it_));
                        hn->swapIndexes(tmp_gates_union);
                
                        for(it_ = pt_gates_insert.begin(); it_ != pt_gates_insert.end(); it_++)
                        {
                                worklist.push(C->getGate(*it_));
                                C->getGate(*it_)->HG_ID = hn->index;
                        }
                
                        if(hn->inputs_.size() > 2)
                                flag = 1;
                }
        }
        else 
        {
                //do not include the gate
                if(tmp_inputs_union.size() - pt_inputs_remove.size() > hn->inputs_.size())
                {
                        return true;
                }
                else
                {
                        hn->inputs_.clear();
                        for(it = tmp_inputs_union.begin(); it != tmp_inputs_union.end(); it++)
                                if(find(pt_inputs_remove.begin(),pt_inputs_remove.end(),*it) == pt_inputs_remove.end())
                                        hn->inputs_.push_back(*it);
                        
                        hn->internal.insert(hn->internal.begin(),pt_inputs_remove.begin(),pt_inputs_remove.end());
                        //use this as a temporary container
                        it_ = set_union(hn->indexes.begin(),hn->indexes.end(), pt_gates_insert.begin(), pt_gates_insert.end(), tmp_gates_union.begin());
                        tmp_gates_union.resize(distance(tmp_gates_union.begin(), it_));
                        hn->swapIndexes(tmp_gates_union);
                        
                        for(it_ = pt_gates_insert.begin(); it_ != pt_gates_insert.end(); it_++)
                        {
                                worklist.push(C->getGate(*it_));
                                C->getGate(*it_)->HG_ID = hn->index;
                        }
                }
        }
        
        int mark;
        tmp_inputs.clear();
        for(it = hn->inputs_.begin(); it != hn->inputs_.end(); )
        {
                mark = 0;
                //cout<<*it<<endl;
                
                if( C->getSignal(*it)->outputSize() == 2 && 
                    find(hn->indexes.begin(), hn->indexes.end(), C->getSignal(*it)->getOutput(0)->getGateIndex()) != hn->indexes.end() &&
                    find(hn->indexes.begin(), hn->indexes.end(), C->getSignal(*it)->getOutput(1)->getGateIndex()) != hn->indexes.end() )
                {
                        if(C->getSignal(*it)->inputSize() != 0)
                        {
                                
                                hn->internal.insert(hn->internal.begin(),*it);
                                                                
                                hn->addIndex(C->getSignal(*it)->getInput(0)->getGateIndex());
                                C->getSignal(*it)->getInput(0)->HG_ID = hn->index;
                                worklist.push(C->getSignal(*it)->getInput(0));
                                
                                for(int j = 0; j < C->getSignal(*it)->getInput(0)->inputSize(); j++)
                                        hn->addInput(C->getSignal(*it)->getInput(0)->getInput(j)->getIndex());
                                
                                it2 = hn->findInput(*it);
                                it = hn->delInput(it2);
                                
                                mark = 1;
                        }
                        
                }
                if(mark == 0)
                        it++;
        }
        
        hn->inputs_.sort();
        it2 = unique(hn->inputs_.begin(),hn->inputs_.end());
        hn->inputs_.resize(distance(hn->inputs_.begin(), it2));
        
        hn->internal.sort();
        it2 = unique(hn->internal.begin(),hn->internal.end());
        hn->internal.resize(distance(hn->internal.begin(), it2));
/*        
        cout<<"inputs............."<<endl;
        dumpInputs(hn->inputs);
        cout<<"internal............."<<endl;
        dumpInputs(hn->internal);
        cout<<"potential remove............."<<endl;
        dumpInputs(pt_inputs_remove);
*/        
        return false;
}

bool formHybrid()
{
        int i,j,gi,flag;
        int level;
        HG_CNT = 0;
        
        //initialization
        for(gi=0; gi<C->gateSize(); ++gi){
                C->getGate(gi)->HG_ID = -1;
        }
        
        //find "suspicious" gates
        for(gi=0; gi<C->gateSize(); ++gi){
                
                flag = 0;
                if(C->getGate(gi)->correlated == 1)
                {
                        //cout<<"Gate Output Name "<<C->getGate(gi)->getOutput(0)->getName()<<endl;
                        //cout<<"Gate ID "<<gi<<endl;
                                                
                        HybridNode* hn= new HybridNode();
                        hn->index = HG_CNT;
                        
                        //add the outputs of the H-Gate
                        for(i = 0; i < C->getGate(gi)->inputSize(); i++)
                        {
                                if(C->getGate(gi)->getInput(i)->outputSize() != 1)
                                {
                                        flag = 1;
                                        break;
                                }
                        }
                        
                        if(flag == 1)
                        {
                                delete hn;
                        }
                        else
                        {
                                if(C->getGate(gi)->HG_ID == -1)
                                {
                                        hn->addOutput(C->getGate(gi)->getOutput(0)->getIndex());                
                                        for(i = 0; i< C->getGate(gi)->inputSize(); i++)
                                                hn->addInput(C->getGate(gi)->getInput(i)->getIndex());                
                                
                                        hn->addIndex(C->getGate(gi)->getGateIndex());
                                        C->getGate(gi)->HG_ID = hn->index;
                                        worklist.push(C->getGate(gi));

                                        while(!worklist.empty())
                                        {
                                                //cout<<"front node's output is "<<worklist.front()->getOutput(0)->getName()<<endl;
                                        
                                                int bound = 0;
                                                if(findPre(worklist.front(),hn, bound) == true)
                                                        break;
                                        
                                                worklist.pop();
                                        }
                                
                                        if(hn->getIndexSize() == 1 || hn->inputs_.size() > 4 || hn->inputs_.size() > hn->indexes.size())
                                        {
                                                C->getGate(hn->getIndex(0))->HG_ID = -1;
                                                hn->clearHG();
                                                delete hn;
                                        }
                                        else
                                        {
                                                calEvents(hn);
                                                moveContainer(hn);
                                                hn->initEvent();
                                                C->addHGate(hn);
                                                HG_CNT++;
                                        }
                                }
                        }
                }
        }
        
	//showFormResult();
	//C->dumpHgates();

        return true;
}
